// SPDX-License-Identifier: GPL-2.0
/******************************************************************************
 *    NAND Flash Controller V301 Device Driver
 *    Copyright (c) 2009-2010 by Hisilicon.
 *    All rights reserved.
 * ***
 *    written by CaiZhiYong. 2010-11-04
 *
 ******************************************************************************/

#ifndef HINFCV301H
#define HINFCV301H
#include "hibase.h"

#ifndef CONFIG_HINFC301_MAX_CHIP
#  define CONFIG_HINFC301_MAX_CHIP                    1
#endif /* CONFIG_HINFC301_MAX_CHIP */

#ifndef CONFIG_HINFC301_REG_BASE_ADDRESS
#ifdef CONFIG_HISI_SD5115_AF_FPGA
#define CONFIG_HINFC301_REG_BASE_ADDRESS            (0x10000000)
#else
#define CONFIG_HINFC301_REG_BASE_ADDRESS            (0x10A30000) /* NANDC Reg */
#endif
#endif

#ifndef CONFIG_HINFC301_BUFFER_BASE_ADDRESS
#ifdef CONFIG_HISI_SD5115_AF_FPGA
#define CONFIG_HINFC301_BUFFER_BASE_ADDRESS         (0x50000000)
#else
#define CONFIG_HINFC301_BUFFER_BASE_ADDRESS         (0x20000000)
#endif
#endif

#ifndef CONFIG_HINFC301_PERIPHERY_REGBASE
#define CONFIG_HINFC301_PERIPHERY_REGBASE 0
#endif

#ifndef CONFIG_HINFC301_W_LATCH
#define CONFIG_HINFC301_W_LATCH                     (5)
#endif

#ifndef CONFIG_HINFC301_R_LATCH
#define CONFIG_HINFC301_R_LATCH                     (5)
#endif

#ifndef CONFIG_HINFC301_RW_LATCH
#define CONFIG_HINFC301_RW_LATCH                    (3)
#endif

#define HINFC301_REG_BASE_ADDRESS_LEN               (0x100)
#define HINFC301_BUFFER_BASE_ADDRESS_LEN            (2048 + 128)

#define HINFC301_CHIP_DELAY                         (25)
#define HINFC301_CHIP_RESET_DELAY                   (50)

#define HINFC301_ADDR_CYCLE_MASK                    0x4

#define HINFC301_CON                                0x00
#define HINFC301_CON_OP_MODE_NORMAL                 (1U << 0)
#define HINFC301_CON_PAGEISZE_SHIFT                 (1)

#define HINFC301_MPW_CON_PAGESIZE_MASK              (0x03)
#define HINFC301_MPW_CON_BUS_WIDTH                  (1U << 3)
#define HINFC301_MPW_CON_READY_BUSY_SEL             (1U << 7)
#define HINFC301_MPW_CON_ECCTYPE_SHIFT              (8)

#define HINFC301_CON_PAGESIZE_MASK                  (0x07)
#define HINFC301_CON_BUS_WIDTH                      (1U << 4)
#define HINFC301_CON_READY_BUSY_SEL                 (1U << 8)
#define HINFC301_CON_ECCTYPE_SHIFT                  (9)

#define HINFC301_CON_ECCTYPE_MASK                   (0x07)
#define HINFC301_CON_ECCTYPE_MASK_5118              (0x0f)
#define HINFC301_PWIDTH                             0x04
#define SET_HINFC301_PWIDTH(_w_lcnt, _r_lcnt, _rw_hcnt) \
	((_w_lcnt) | (((_r_lcnt) & 0x0F) << 4) | (((_rw_hcnt) & 0x0F) << 8))

#define HINFC301_CMD                                0x0C
#define HINFC301_ADDRL                              0x10
#define HINFC301_ADDRH                              0x14

#define HINFC301_OP                      0x1C
#define HINFC301_OP_READ_STATUS_EN       (1U << 0)
#define HINFC301_OP_READ_DATA_EN         (1U << 1)
#define HINFC301_OP_WAIT_READY_EN        (1U << 2)
#define HINFC301_OP_CMD2_EN              (1U << 3)
#define HINFC301_OP_WRITE_DATA_EN        (1U << 4)
#define HINFC301_OP_ADDR_EN              (1U << 5)
#define HINFC301_OP_CMD1_EN              (1U << 6)
#define HINFC301_OP_NF_CS_SHIFT          (7)
#define HINFC301_OP_NF_CS_MASK           (3)
#define HINFC301_OP_ADDR_CYCLE_SHIFT     (9)
#define HINFC301_OP_ADDR_CYCLE_MASK      (7)

#define HINFC301_STATUS                  0x20

#define HINFC301_INTS                    0x28
#define HINFC301_INTS_UE                 (1U << 6)
#define HINFC301_INTCLR                  0x2C
#define HINFC301_INTCLR_UE               (1U << 6)

#define HINFC301_DMA_CTRL                0x60
#define HINFC301_DMA_CTRL_DMA_START      (1U << 0)
#define HINFC301_DMA_CTRL_WE             (1U << 1)
#define HINFC301_DMA_CTRL_DATA_AREA_EN   (1U << 2)
#define HINFC301_DMA_CTRL_OOB_AREA_EN    (1U << 3)
#define HINFC301_DMA_CTRL_BURST4_EN      (1U << 4)
#define HINFC301_DMA_CTRL_BURST8_EN      (1U << 5)
#define HINFC301_DMA_CTRL_BURST16_EN     (1U << 6)
#define HINFC301_DMA_CTRL_ADDR_NUM_SHIFT (7)
#define HINFC301_DMA_CTRL_ADDR_NUM_MASK  (1)
#define HINFC301_DMA_CTRL_CS_SHIFT       (8)
#define HINFC301_DMA_CTRL_CS_MASK        (0x03)

#define HINFC301_DMA_ADDR_DATA           0x64
#define HINFC301_DMA_ADDR_OOB            0x68

#define HINFC301_DMA_LEN                 0x6C
#define HINFC301_DMA_LEN_OOB_SHIFT       (16)
#define HINFC301_DMA_LEN_OOB_MASK        (0xFFF)

#define HINFC301_DMA_PARA                 0x70
#define HINFC301_DMA_PARA_DATA_RW_EN     (1U << 0)
#define HINFC301_DMA_PARA_OOB_RW_EN      (1U << 1)
#define HINFC301_DMA_PARA_DATA_EDC_EN    (1U << 2)
#define HINFC301_DMA_PARA_OOB_EDC_EN     (1U << 3)
#define HINFC301_DMA_PARA_DATA_ECC_EN    (1U << 4)
#define HINFC301_DMA_PARA_OOB_ECC_EN     (1U << 5)
#define HINFC301_DMA_PARA_EXT_LEN_SHIFT  (6)
#define HINFC301_DMA_PARA_EXT_LEN_MASK   (0x03)

#define HINFC301_LOG_READ_ADDR           0x7C
#define HINFC301_LOG_READ_LEN            0x80
#define HINFC301_NFC_BOOT_SET            0x94

#define NAND_FLASH_TYPE                  1
#define SPI_NAND_FLASH_TYPE              2

#define NFC_512B                               (512)
#define NFC_2K                                 (2048)
#define NFC_4K                                 (4096)
#define NFC_8K                                 (8192)
#define NFC_16K                                (0x4000)
#define NFC_32K                                (0x8000)

#define PERI_CRG30                                     (0x00B8)
#define PERI_CRG30_CLK_EN                              (1U << 8)
#define PERI_CRG30_CLK_SEL_99M                         (1U << 16)

#define HINFC301_CHECK_STATUS_LOOP_MAX      10000000

enum ecc_nfc_type {
	et_ecc_none = 0x00,
	et_ecc_1bit = 0x01,
	et_ecc_4bytes = 0x02,
	et_ecc_8bytes = 0x03,
	et_ecc_24bit1k = 0x04,
	et_ecc_16bit1k = 0x06,
};

enum ecc_5610_type {
	et_ecc_5610_none = 0x00,
	et_ecc_5610_1bit = 0x01,
	et_ecc_5610_4bytes = 0x02,
	et_ecc_5610_8bytes = 0x03,
	et_ecc_5610_24bit1k = 0x04,
	et_ecc_5610_40bit = 0x05,
	et_ecc_5610_64bit = 0x06,
};

enum ecc_5118_type {
	et_ecc_5118_none = 0x00,
	et_ecc_5118_8bit = 0x01,
	et_ecc_5118_13bit = 0x02,
	et_ecc_5118_18bit = 0x03,
	et_ecc_5118_24bit = 0x04,
	et_ecc_5118_27bit = 0x05,
	et_ecc_5118_32bit = 0x06,
	et_ecc_5118_41bit = 0x07,
	et_ecc_5118_48bit = 0x08,
	et_ecc_5118_60bit = 0x09,
	et_ecc_5118_72bit = 0x0A,
	et_ecc_5118_80bit = 0x0B,
};

enum page_type {
	pt_pagesize_512 = 0x00,
	pt_pagesize_2K = 0x01,
	pt_pagesize_4K = 0x02,
	pt_pagesize_8K = 0x03,
};

#define HINFC301_CON_BLOCKSIZE_MASK 0x3

enum block_type {
	nfc_blocksize_64 = 0x00,
	nfc_blocksize_128 = 0x01,
	nfc_blocksize_256 = 0x02,
	nfc_blocksize_512 = 0x03,
};

struct page_page_ecc_info {
	enum page_type pagetype;
	unsigned int ecctype;
	unsigned int oobsize;
	//struct nand_ecclayout *layout;
	struct mtd_ooblayout_ops *layout;
};

void hinfc301_controller_enable(struct hinfc_host *host, int enable);
extern void (*nand_base_oob_resize)(struct mtd_info *mtd, struct nand_chip *chip);
extern hi_chip_id_e hi_kernel_get_chip_id(void);
extern struct nand_flash_dev *(*nand_base_get_special_flash_type)(
	unsigned char id[8], struct nand_chip *chip);

int hinfc301_chip_reset_test(struct hinfc_host *host);
int hinfc301_nand_init(struct hinfc_host *host, struct nand_chip *chip);

#ifdef CONFIG_PM
int hinfc301_suspend(struct platform_device *pltdev, pm_message_t state);
int hinfc301_resume(struct platform_device *pltdev);
#endif

#endif
